package com.example.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class PythonScriptService {

    @Value("${analysis.python-script-dir}")
    private String pythonScriptDir;

    @Value("${analysis.temp-dir}")
    private String tempDir;

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 执行第一次皮尔逊相关系数分析
     */
    public Map<String, Object> executeFirstCorrelationScript(String csvFilePath) {
        String scriptPath = Paths.get(pythonScriptDir, "first_correlation_analysis.py").toString();
        return executePythonScript(scriptPath, csvFilePath);
    }

    /**
     * 执行第二次皮尔逊相关系数分析
     */
    public Map<String, Object> executeSecondCorrelationScript(String csvFilePath, String selectedFeaturesJson) {
        try {
            // 验证输入文件
            if (!Files.exists(Paths.get(csvFilePath))) {
                return Map.of(
                        "status", "error",
                        "message", "CSV文件不存在: " + csvFilePath
                );
            }

            // 创建临时JSON文件
            Path tempJsonFile = Paths.get(tempDir, "selected_features_" + System.currentTimeMillis() + ".json");
            Files.write(tempJsonFile, selectedFeaturesJson.getBytes("UTF-8"));

            // 验证JSON文件内容
            log.info("临时特征文件: {}, 内容: {}", tempJsonFile, selectedFeaturesJson);

            String scriptPath = Paths.get(pythonScriptDir, "second_correlation_analysis.py").toString();

            // 验证Python脚本文件
            if (!Files.exists(Paths.get(scriptPath))) {
                return Map.of(
                        "status", "error",
                        "message", "Python脚本文件不存在: " + scriptPath
                );
            }

            Map<String, Object> result = executePythonScript(scriptPath, csvFilePath, tempJsonFile.toString());

            // 清理临时文件
            try {
                Files.deleteIfExists(tempJsonFile);
            } catch (Exception e) {
                log.warn("删除临时JSON文件失败: {}", e.getMessage());
            }

            // 验证返回结果
            if (result == null || result.isEmpty()) {
                log.error("Python脚本执行结果为空");
                return Map.of(
                        "status", "error",
                        "message", "Python脚本没有返回有效结果"
                );
            }

            return result;
        } catch (Exception e) {
            log.error("执行第二次相关性分析失败", e);
            return Map.of(
                    "status", "error",
                    "message", "第二次相关性分析执行失败: " + e.getMessage()
            );
        }
    }



    /**
     * 执行第一次ANOVA分析Python脚本 - 找出F统计量最高的前20个特征
     * @param csvFilePath CSV数据文件路径
     * @return ANOVA分析结果，包含前20个特征
     */
    public Map<String, Object> executeFirstAnovaScript(String csvFilePath) {
        String scriptPath = Paths.get(pythonScriptDir, "first_anova_analysis.py").toString();
        return executePythonScript(scriptPath, csvFilePath);
    }

    /**
     * 执行第二次ANOVA分析Python脚本 - 对选定的21个字段进行详细分析
     * @param csvFilePath 21个字段的CSV文件路径
     * @param selectedFeaturesJson 选定特征的JSON字符串
     * @return 详细的ANOVA分析结果，包含可视化图表
     */
    public Map<String, Object> executeSecondAnovaScript(String csvFilePath, String selectedFeaturesJson) {
        try {
            // 将JSON写入临时文件，避免命令行参数问题
            Path tempJsonFile = Paths.get(tempDir, "selected_features_" + System.currentTimeMillis() + ".json");
            Files.write(tempJsonFile, selectedFeaturesJson.getBytes("UTF-8"));

            log.info("特征列表已写入临时文件: {}", tempJsonFile);
            log.info("特征JSON内容: {}", selectedFeaturesJson);

            String scriptPath = Paths.get(pythonScriptDir, "second_anova_analysis.py").toString();

            // 传递文件路径
            Map<String, Object> result = executePythonScript(scriptPath, csvFilePath, tempJsonFile.toString());

            // 清理临时文件
            try {
                Files.deleteIfExists(tempJsonFile);
            } catch (Exception e) {
                log.warn("删除临时JSON文件失败: {}", e.getMessage());
            }

            return result;

        } catch (Exception e) {
            log.error("执行第二次ANOVA分析失败", e);
            Map<String, Object> errorResult = Map.of(
                    "status", "error",
                    "message", "第二次ANOVA分析执行失败: " + e.getMessage()
            );
            return errorResult;
        }
    }

    /**
     * 执行IterativeImputer插补Python脚本
     * @param csvFilePath 要插补的CSV文件路径
     * @return 插补结果和统计信息
     */
    public Map<String, Object> executeImputationScript(String csvFilePath) {
        String scriptPath = Paths.get(pythonScriptDir, "iterative_imputation.py").toString();
        return executePythonScript(scriptPath, csvFilePath);
    }

    /**
     * 执行随机森林填充脚本
     * @param selectedCsvPath 选定的21个字段CSV文件路径
     * @return 随机森林填充结果
     */
    public Map<String, Object> executeRfImputationScript(String selectedCsvPath) {
        String scriptPath = Paths.get(pythonScriptDir, "rf_imputation.py").toString();
        return executePythonScript(scriptPath, selectedCsvPath);
    }


    /**
     * 执行噪声扩充Python脚本
     * @param csvFilePath 插补后的CSV文件路径
     * @param targetSamples 目标样本数量
     * @return 噪声扩充结果
     */
    public Map<String, Object> executeAugmentationScript(String csvFilePath, int targetSamples) {
        String scriptPath = Paths.get(pythonScriptDir, "noise_augmentation.py").toString();
        return executePythonScript(scriptPath, csvFilePath, String.valueOf(targetSamples));
    }


    /**
     * 执行SMOTE扩充脚本
     * @param imputedCsvPath 插补后的CSV文件路径
     * @param targetSamples 目标样本数量
     * @return SMOTE扩充结果
     */
    public Map<String, Object> executeSmoteAugmentationScript(String imputedCsvPath, int targetSamples) {
        String scriptPath = Paths.get(pythonScriptDir, "smote_augmentation.py").toString();
        return executePythonScript(scriptPath, imputedCsvPath, String.valueOf(targetSamples));
    }

    /**
     * 通用Python脚本执行方法
     * 负责启动Python进程、传递参数、收集输出并解析JSON结果
     * @param scriptPath Python脚本的完整路径
     * @param args 传递给Python脚本的参数数组
     * @return 解析后的脚本执行结果Map
     */
    private Map<String, Object> executePythonScript(String scriptPath, String... args) {
        try {
            // 确保临时目录存在
            Files.createDirectories(Paths.get(tempDir));
            Files.createDirectories(Paths.get(tempDir, "output"));

            // 验证脚本文件存在
            if (!Files.exists(Paths.get(scriptPath))) {
                throw new RuntimeException("Python脚本文件不存在: " + scriptPath);
            }

            // 构建Python命令
            ProcessBuilder processBuilder = new ProcessBuilder();
            processBuilder.command("python", scriptPath);
            for (String arg : args) {
                if (arg != null && !arg.trim().isEmpty()) {
                    processBuilder.command().add(arg);
                }
            }

            // 设置工作目录和环境变量
            processBuilder.directory(new File(System.getProperty("user.dir")));
            Map<String, String> env = processBuilder.environment();
            env.put("PYTHONIOENCODING", "utf-8");
            env.put("PYTHONPATH", ".");

            log.info("执行Python脚本命令: {}", String.join(" ", processBuilder.command()));

            // 启动Python进程
            Process process = processBuilder.start();

            // 分别读取标准输出和错误输出
            StringBuilder output = new StringBuilder();
            StringBuilder errorOutput = new StringBuilder();

            // 读取标准输出
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), "UTF-8"))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                }
            }

            // 读取错误输出
            try (BufferedReader errorReader = new BufferedReader(
                    new InputStreamReader(process.getErrorStream(), "UTF-8"))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    errorOutput.append(line).append("\n");
                    log.debug("Python错误输出: {}", line);
                }
            }

            // 等待脚本执行完成
            boolean finished = process.waitFor(10, TimeUnit.MINUTES);
            if (!finished) {
                process.destroyForcibly();
                throw new RuntimeException("Python脚本执行超时（10分钟）");
            }

            // 检查退出码
            int exitCode = process.exitValue();
            if (exitCode != 0) {
                log.error("Python脚本执行失败，退出码: {}", exitCode);
                log.error("标准输出: {}", output.toString());
                log.error("错误输出: {}", errorOutput.toString());
                throw new RuntimeException("Python脚本执行失败，退出码: " + exitCode +
                        ", 标准输出: " + output.toString() +
                        ", 错误输出: " + errorOutput.toString());
            }

            // 解析JSON输出
            String jsonOutput = output.toString().trim();
            if (jsonOutput.isEmpty()) {
                throw new RuntimeException("Python脚本没有输出结果");
            }

            // 查找最后一行有效的JSON
            String[] lines = jsonOutput.split("\n");
            String validJson = null;
            for (int i = lines.length - 1; i >= 0; i--) {
                String line = lines[i].trim();
                if (line.startsWith("{") && line.endsWith("}")) {
                    validJson = line;
                    break;
                }
            }

            if (validJson == null) {
                log.error("未找到有效的JSON输出，原始输出: {}", jsonOutput);
                throw new RuntimeException("Python脚本输出格式错误，未找到有效JSON");
            }

            // 解析JSON
            try {
                @SuppressWarnings("unchecked")
                Map<String, Object> result = objectMapper.readValue(validJson, Map.class);
                log.info("Python脚本执行成功，状态: {}", result.get("status"));
                return result;
            } catch (Exception e) {
                log.error("JSON解析失败，原始输出: {}", validJson);
                throw new RuntimeException("解析Python脚本输出JSON失败: " + e.getMessage());
            }

        } catch (Exception e) {
            log.error("执行Python脚本异常: {}", e.getMessage(), e);
            throw new RuntimeException("Python脚本执行失败: " + e.getMessage(), e);
        }
    }
}